<?php

namespace app;

use app\exception\CommonException;
use app\utils\BaseVarDumper;
use think\db\exception\DataNotFoundException;
use think\db\exception\ModelNotFoundException;
use think\exception\ClassNotFoundException;
use think\exception\Handle;
use think\exception\HttpException;
use think\exception\HttpResponseException;
use think\exception\RouteNotFoundException;
use think\exception\ValidateException;
use think\exception\InvalidArgumentException;
use think\facade\Log;
use Throwable;

/**
 * 应用异常处理类
 */
class ExceptionHandle extends Handle
{
    /**
     * 不需要记录信息（日志）的异常类列表
     * @var array
     */
    protected $ignoreReport = [
        HttpResponseException::class,
        ValidateException::class,
        DataNotFoundException::class,
        ModelNotFoundException::class,
    ];

    /**
     * Render an exception into an HTTP response.
     *
     * @access public
     * @param \think\Request $request
     * @param Throwable $e
     * @return mixed
     */
    public function render($request, Throwable $e): \think\Response
    {

        if ($e instanceof HttpResponseException) {
            return parent::render($request, $e);
        }


        $debug = $this->app->isDebug();
        $module = $this->app->http->getName();
        // ajax请求异常 , 不返回错误页面
        if ($e instanceof CommonException) {
            if ($request->isAjax()) {
                $message = $debug ? $e->getMessage():"系统错误";
                return json(['msg' => $message, "code" => $e->getCode(), "log_id" => create_log_id()]);
            }
            return $debug ? parent::render($request, $e):view($this->app->getAppPath() .DS."view".DS."error".DS."500.html", ["log_id" => create_log_id(), "msg" => "系统错误"], 500);
        }
        if ($e instanceof ValidateException) {
            if ($request->isAjax()) {
                return json(["msg" => $e->getError(), "code" => 422, "log_id" => create_log_id()]);
            }
            return view($this->app->getAppPath() .DS."view".DS."error".DS."jump.html", ["log_id" => create_log_id(), "msg" => "系统错误"], 422);

        }
        //类未找到, 返回错误页面
        if (($e instanceof ClassNotFoundException || $e instanceof RouteNotFoundException)|| ($e instanceof HttpException && $e->getStatusCode() == 404)) {
            if ($request->isAjax()) {
                $msg = $debug ? "当前请求资源不存在，请稍后再试":$e->getMessage();
                return json(['msg' =>$msg, 'code' => 404, "log_id" => create_log_id()]);
            }
            return view($this->app->getAppPath().DS."view".DS."error".DS."404.html", ["log_id" => create_log_id(), "msg" => "请求资源不存在"], 404);
        }

        if ($e instanceof \Exception || $e instanceof \PDOException || $e instanceof InvalidArgumentException || $e instanceof \ErrorException || $e instanceof \ParseError || $e instanceof \TypeError || ($e instanceof HttpException && $e->getStatusCode() == 500)) {
            if ($request->isAjax()) {
                $msg = $debug ? $e->getMessage():"系统错误";
                return json(['msg' =>$msg, 'code' => 500, "log_id" => create_log_id()]);
            }
            return $debug ? parent::render($request, $e) :view($this->app->getAppPath().DS."view".DS."error".DS."500.html", ["log_id" => create_log_id(), "msg" => "系统错误"], 500);
        }
        // 其他错误交给系统处理
        return parent::render($request, $e);
    }

    /**
     * 记录异常信息（包括日志或者其它方式记录）
     *
     * @access public
     * @param Throwable $exception
     * @return void
     */
    public function report(Throwable $e): void
    {

        if (!$this->isIgnoreReport($e)) {
            $data = [
                'file' => $e->getFile(),
                'line' => $e->getLine(),
                'message' => $this->getMessage($e),
                'code' => $this->getCode($e),
                 'trace' => $e->getTrace(),
                'previous' => $e->getPrevious(),
            ];

            Log::error("error={error}", ["error" => BaseVarDumper::dumpAsString($data)]);
        }
    }
}
